package com.eyun.system.service;

import cn.hutool.core.bean.BeanUtil;
import com.eyun.security.SecurityUtils;
import com.eyun.system.domain.AnnouncementRecord;
import com.eyun.system.repository.AnnouncementRecordRepository;
import com.eyun.system.service.dto.AnnouncementDTO;
import com.eyun.system.service.dto.AnnouncementRecordDTO;
import com.eyun.system.service.mapper.AnnouncementRecordMapper;
import java.time.ZonedDateTime;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.CacheManager;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.ExampleMatcher;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

// jhipster-needle-add-import - JHipster will add getters and setters here, do not remove

/**
 * Service Implementation for managing {@link AnnouncementRecord}.
 */
@Service
@Transactional
public class AnnouncementRecordService {

    private final Logger log = LoggerFactory.getLogger(AnnouncementRecordService.class);

    private final AnnouncementRecordRepository announcementRecordRepository;

    private final CacheManager cacheManager;

    private final AnnouncementRecordMapper announcementRecordMapper;

    public AnnouncementRecordService(
        AnnouncementRecordRepository announcementRecordRepository,
        CacheManager cacheManager,
        AnnouncementRecordMapper announcementRecordMapper
    ) {
        this.announcementRecordRepository = announcementRecordRepository;
        this.cacheManager = cacheManager;
        this.announcementRecordMapper = announcementRecordMapper;
    }

    /**
     * Save a announcementRecord.
     *
     * @param announcementRecordDTO the entity to save.
     * @return the persisted entity.
     */
    public AnnouncementRecordDTO save(AnnouncementRecordDTO announcementRecordDTO) {
        log.debug("Request to save AnnouncementRecord : {}", announcementRecordDTO);
        AnnouncementRecord announcementRecord = announcementRecordMapper.toEntity(announcementRecordDTO);
        announcementRecord = announcementRecordRepository.save(announcementRecord);
        return announcementRecordMapper.toDto(announcementRecord);
    }

    /**
     * Partially update a announcementRecord.
     *
     * @param announcementRecordDTO the entity to update partially.
     * @return the persisted entity.
     */
    public Optional<AnnouncementRecordDTO> partialUpdate(AnnouncementRecordDTO announcementRecordDTO) {
        log.debug("Request to partially update AnnouncementRecord : {}", announcementRecordDTO);

        return announcementRecordRepository
            .findById(announcementRecordDTO.getId())
            .map(
                existingAnnouncementRecord -> {
                    announcementRecordMapper.partialUpdate(existingAnnouncementRecord, announcementRecordDTO);

                    return existingAnnouncementRecord;
                }
            )
            .map(announcementRecordRepository::save)
            .map(announcementRecordMapper::toDto);
    }

    /**
     * Get all the announcementRecords.
     *
     * @param pageable the pagination information.
     * @return the list of entities.
     */
    @Transactional(readOnly = true)
    public Page<AnnouncementRecordDTO> findAll(Pageable pageable) {
        log.debug("Request to get all AnnouncementRecords");
        return announcementRecordRepository.findAll(pageable).map(announcementRecordMapper::toDto);
    }

    public void updateRecord(List<AnnouncementDTO> announcementDTOS) {
        Long userId = SecurityUtils.getCurrentUserId().get();
        announcementDTOS.forEach(
            announcementDTO -> {
                Long anntId = announcementDTO.getId();
                if (
                    !announcementRecordRepository.exists(
                        Example.of(new AnnouncementRecord().anntId(announcementDTO.getId()).userId(userId))
                    )
                ) {
                    announcementRecordRepository.save(new AnnouncementRecord().anntId(anntId).userId(userId));
                }
            }
        );
    }

    public void setRead(Long anntId) {
        Long userId = SecurityUtils.getCurrentUserId().get();

        Optional<AnnouncementRecord> one = announcementRecordRepository.findOne(
            Example.of(new AnnouncementRecord().anntId(anntId).userId(userId))
        );
        if (one.isPresent()) {
            one.get().hasRead(true).readTime(ZonedDateTime.now());
            announcementRecordRepository.save(one.get());
        }
    }

    /**
     * count all the announcementRecords.
     * @return the count of entities
     */
    @Transactional(readOnly = true)
    public long count() {
        log.debug("Request to count all AnnouncementRecords");
        return announcementRecordRepository.count();
    }

    /**
     * Get one announcementRecord by id.
     *
     * @param id the id of the entity.
     * @return the entity.
     */
    @Transactional(readOnly = true)
    public Optional<AnnouncementRecordDTO> findOne(Long id) {
        log.debug("Request to get AnnouncementRecord : {}", id);
        return announcementRecordRepository.findById(id).map(announcementRecordMapper::toDto);
    }

    /**
     * Get one announcementRecord by example.
     *
     * @param example the example of the entity.
     * @return the entity.
     */
    @Transactional(readOnly = true)
    public Optional<AnnouncementRecordDTO> findOneByExample(Example<AnnouncementRecord> example) {
        log.debug("Request to get AnnouncementRecord by example");
        return announcementRecordRepository.findOne(example).map(announcementRecordMapper::toDto);
    }

    /**
     * Get all the announcementRecords by example.
     *
     * @param example the example of the entity.
     * @return the entities.
     */
    @Transactional(readOnly = true)
    public Page<AnnouncementRecordDTO> findAllByExample(Example<AnnouncementRecord> example, Pageable pageable) {
        log.debug("Request to get AnnouncementRecord by example");
        return announcementRecordRepository.findAll(example, pageable).map(announcementRecordMapper::toDto);
    }

    /**
     * Delete the announcementRecord by id.
     *
     * @param id the id of the entity.
     */
    public void delete(Long id) {
        log.debug("Request to delete AnnouncementRecord : {}", id);
        announcementRecordRepository.deleteById(id);
    }

    /**
     * Update ignore specified fields by announcementRecord
     */
    public AnnouncementRecordDTO updateByIgnoreSpecifiedFields(
        AnnouncementRecordDTO changeAnnouncementRecordDTO,
        Set<String> unchangedFields
    ) {
        AnnouncementRecordDTO announcementRecordDTO = findOne(changeAnnouncementRecordDTO.getId()).get();
        BeanUtil.copyProperties(changeAnnouncementRecordDTO, announcementRecordDTO, unchangedFields.toArray(new String[0]));
        announcementRecordDTO = save(announcementRecordDTO);
        return announcementRecordDTO;
    }

    /**
     * Update specified fields by announcementRecord
     */
    public AnnouncementRecordDTO updateBySpecifiedFields(AnnouncementRecordDTO changeAnnouncementRecordDTO, Set<String> fieldNames) {
        AnnouncementRecordDTO announcementRecordDTO = findOne(changeAnnouncementRecordDTO.getId()).get();
        AnnouncementRecordDTO finalAnnouncementRecordDTO = announcementRecordDTO;
        fieldNames.forEach(
            fieldName -> {
                BeanUtil.setFieldValue(
                    finalAnnouncementRecordDTO,
                    fieldName,
                    BeanUtil.getFieldValue(changeAnnouncementRecordDTO, fieldName)
                );
            }
        );
        announcementRecordDTO = save(finalAnnouncementRecordDTO);
        return announcementRecordDTO;
    }

    /**
     * Update specified field by announcementRecord
     */
    public AnnouncementRecordDTO updateBySpecifiedField(AnnouncementRecordDTO changeAnnouncementRecordDTO, String fieldName) {
        AnnouncementRecordDTO announcementRecordDTO = findOne(changeAnnouncementRecordDTO.getId()).get();
        BeanUtil.setFieldValue(announcementRecordDTO, fieldName, BeanUtil.getFieldValue(changeAnnouncementRecordDTO, fieldName));
        announcementRecordDTO = save(announcementRecordDTO);
        return announcementRecordDTO;
    }
    // jhipster-needle-service-add-method - JHipster will add getters and setters here, do not remove

}
